package sample.methodremoveinstruct;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.util.ASMifier;
import org.objectweb.asm.util.CheckClassAdapter;
import org.objectweb.asm.util.Textifier;
import util.FileUtils;

import java.io.IOException;
import java.io.PrintWriter;

import static org.objectweb.asm.Opcodes.ASM9;

public class MethodRemovePipelineDemo {
    public static void main(String[] args) throws IOException {
        Class<?> clazz = HelloWorld.class;
        byte[] bytes = invoke(clazz);
        //  output
        FileUtils.writeBytes(Type.getInternalName(clazz) + "RemovePipeline.class", bytes);
        //  replace
        FileUtils.writeBytes(clazz.getResource("/").getPath() + Type.getInternalName(clazz) + ".class", bytes);

        CheckClassAdapter.verify(new ClassReader(bytes), false, new PrintWriter(System.out));
        String[] methodArgs = {"-debug", Type.getInternalName(clazz) + "RemovePipeline.class"};
        ASMifier.main(methodArgs);
        Textifier.main(methodArgs);
    }

    private static byte[] invoke(Class<?> clazz) throws IOException {
        ClassReader classReader = new ClassReader(clazz.getName());
        ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_FRAMES);
        classReader.accept(of(ASM9, classWriter), ClassReader.EXPAND_FRAMES);
        return classWriter.toByteArray();
    }

    private static ClassVisitor of(int api, ClassWriter classWriter) {
        MethodRemoveZeroAddDemo.MethodRemoveZeroAddVisitor visitor1 = new MethodRemoveZeroAddDemo.MethodRemoveZeroAddVisitor(api, classWriter);
        MethodRemoveGetFieldPutFieldDemo.MethodRemoveGetFieldPutFieldVisitor visitor2 = new MethodRemoveGetFieldPutFieldDemo.MethodRemoveGetFieldPutFieldVisitor(api, visitor1);
        MethodRemovePrintStringDemo.MethodRemovePrintStringVisitor visitor3 = new MethodRemovePrintStringDemo.MethodRemovePrintStringVisitor(api, visitor2);
        return visitor3;
    }
}
